package broadcast

type Broadcast struct {
	listeners  []chan any
	reg        chan (chan any)
	unreg      chan (chan any)
	in         chan any
	stop       chan int64
	stopStatus bool
}

func NewBroadcast() *Broadcast {
	b := &Broadcast{
		listeners:  make([]chan any, 0),
		reg:        make(chan chan any),
		unreg:      make(chan chan any),
		in:         make(chan any),
		stop:       make(chan int64),
		stopStatus: false,
	}

	go func() {
		for {
			select {
			case l := <-b.unreg:
				oldListeners := b.listeners
				b.listeners = make([]chan any, 0, len(oldListeners))
				for _, oldL := range oldListeners {
					if l != oldL {
						b.listeners = append(b.listeners, oldL)
					}
				}
			case l := <-b.reg:
				b.listeners = append(b.listeners, l)
			case item := <-b.in:
				for _, l := range b.listeners {
					l <- item
				}
			case <-b.stop:
				b.stopStatus = true
				return
			}
		}
	}()

	return b
}

func (b *Broadcast) In() chan any {
	return b.in
}

func (b *Broadcast) Reg() chan any {
	listener := make(chan any)
	b.reg <- listener
	return listener
}

func (b *Broadcast) UnReg(listener chan any) {
	b.unreg <- listener
}

func (b *Broadcast) Close() {
	if !b.stopStatus {
		b.stop <- 1
	}
}

func (b *Broadcast) Stop() {}
